#ifndef __NPC__CASTINGS_H__
#define __NPC__CASTINGS_H__

#include <string>
#include <vector>
#include <jni.h>
#include "C:\Program Files\Java\jdk1.6.0_13\include\jni.h"

const char* pointer_signature = "J";

const char* pointer_field_name = "pointer";

static jclass native_class = NULL;

static jfieldID pointer_field = NULL;

void start_conexion(JNIEnv* env, jclass native_class){
	native_class = (jclass)env->NewWeakGlobalRef(native_class);
	load_pointer_field(env);
	stringClass = env->FindClass(stringClassSignature);
	stringClass = (jclass)env->NewWeakGlobalRef(stringClass);
	stringArrayClass = env->FindClass(stringArrayClassSignature);
	stringArrayClass = (jclass)env->NewWeakGlobalRef(stringArrayClass);
}

void close_conexion(JNIEnv* env, jclass native_class){
	env->DeleteWeakGlobalRef(native_class);
}

void load_pointer_field(JNIEnv* env){
	pointer_field=env->GetFieldID(native_class, pointer_field_name, pointer_signature);
}

native_class* load_native_object(JNIEnv* env, jobject obj){
	return reinterpret_cast<native_class*>(env->GetIntField(obj, pointer_field));
}

inline string castToNative_String(JNIEnv* env, jstring s){
	const char* buffer=env->GetStringUTFChars(s, NULL);
	if(!buffer)
		throw 1;
	string res=string(buffer);
	env->ReleaseStringUTFChars(s,buffer);
	return res;
}

inline jstring castFromNative_String(JNIEnv* env, string s){
	return env->NewStringUTF(s.c_str());
}

jobjectArray cast_vector_string2jobjectArray(JNIEnv* env, vector<string> v){
	int size=v.size();
	jobjectArray a=env->NewObjectArray(size, stringClass, NULL);
	for(int i=0; i<size; i++){
		jstring s=cast_string2jstring(env, v[i]);
		env->SetObjectArrayElement(a, i, s);
	}
	return a;
}

vector<string> cast_jobjectArray2vector_string(JNIEnv* env, jobjectArray a){
	int size=env->GetArrayLength(a);
	vector<string> v=vector<string>(size);
	for(int i=0; i<size; i++){
		v[i]=cast_jstring2string(env, (jstring)env->GetObjectArrayElement(a, i));
	}
	return v;
}

jintArray castVector_int2jintArray(JNIEnv* env, vector<int> v){
	int size=v.size();
	jintArray a=env->NewIntArray(size);
	jint* buffer=(jint*)env->GetPrimitiveArrayCritical(a, NULL);
	for(int i=0; i<size; i++)
		buffer[i]=v[i];
	env->ReleasePrimitiveArrayCritical(a, buffer, 0);
	return a;
}

vector<int> cast_jintArray2vector_int(JNIEnv* env, jintArray a){
	int size=env->GetArrayLength(a);
	vector<int> v=vector<int>(size);
	jint* buffer=env->GetIntArrayElements(a, NULL);
	for(int i=0; i<size; i++)
		v[i]=buffer[i];
	env->ReleaseIntArrayElements(a,buffer, JNI_ABORT);
	return v;
}

jfloatArray castVector_float2jfloatArray(JNIEnv* env, vector<float> v){
	int size=v.size();
	jfloatArray a=env->NewFloatArray(size);
	jfloat* buffer=(jfloat*)env->GetPrimitiveArrayCritical(a, NULL);
	for(int i=0; i<size; buffer[i] = v[i++]);
	env->ReleasePrimitiveArrayCritical(a, buffer, 0);
	return a;
}

vector<float> cast_jfloatArray2vector_float(JNIEnv* env, jfloatArray a){
	int size=env->GetArrayLength(a);
	vector<float> v=vector<float>(size);
	jfloat* buffer=(jfloat*)env->GetPrimitiveArrayCritical(a, NULL);
	for(int i=0; i<size; v[i]=buffer[i++]);
	env->ReleaseFloatArrayElements(a, buffer, JNI_ABORT);
	return v;
}

#endif